# 读取元数据，在数据库中存储节点
# 节点包括：软件包节点、开发者(维护者)节点

import argparse
from utils import *

# 数据库地址






def ana_maintainer(maintain_str):
    try:
        maintain_list = maintain_str.split(" <")
        return maintain_list[0].strip(), ("<" + maintain_list[1]).strip()
    except BaseException:
        print("++++++++++++++Error: Wrong Maintain String Format: " + maintain_str)
        return maintain_str.strip(), ""


def analyse_package(tx, package_dict):
    pkg_name = package_dict['Package']
    ubuntu_release_name = package_dict['Ubuntu-Release-Name']
    pkg_update_type = package_dict['Package-Update-Type']
    pkg_type = package_dict['Package-Type']
    pkg_arch = get_value(package_dict, 'Architecture')
    pkg_ver = get_value(package_dict, 'Version')
    pkg_priority = get_value(package_dict, 'Priority')  # ?
    pkg_section = get_value(package_dict, 'Section')  # ?
    pkg_origin = get_value(package_dict, 'Origin')  # ?
    pkg_maintainer = get_value(package_dict, 'Maintainer')
    pkg_ori_maintainer = get_value(package_dict, 'Original-Maintainer')
    pkg_bugs = get_value(package_dict, 'Bugs')
    pkg_pos = 'http://us.archive.ubuntu.com/ubuntu/' + get_value(package_dict, 'Filename')
    pkg_size = get_value(package_dict, 'Size')  # 软件包大小
    pkg_install_size = get_value(package_dict, 'Installed-Size')  # ?
    pkg_description = get_value(package_dict, 'Description')
    pkg_source = get_value(package_dict, 'Source')
    pkg_homepage = get_value(package_dict, 'Homepage')
    pkg_support = get_value(package_dict, 'Supported')
    pkg_multi_arch = get_value(package_dict, 'Multi-Arch')
    pkg_task = get_value(package_dict, 'Task')  # ?
    pkg_id = pkg_name+pkg_ver
    # 共9种关系
    pkg_depends = get_value(package_dict, 'Depends')
    pkg_pre_depends = get_value(package_dict, 'Pre-Depends')
    pkg_recommends = get_value(package_dict, 'Recommends')
    pkg_suggests = get_value(package_dict, 'Suggests')
    pkg_enhances = get_value(package_dict, 'Enhances')
    pkg_breaks = get_value(package_dict, 'Breaks')
    pkg_conflicts = get_value(package_dict, 'Conflicts')
    pkg_replaces = get_value(package_dict, 'Replaces')
    pkg_provides = get_value(package_dict, 'Provides')

    # 创建包节点
    query = ("CREATE (n:Package{"
             "Id: $pkg_id, IsFinish: $is_finish,"
             "Name: $pkg_name, Ubuntu_Release_Name: $ubuntu_release_name, "
             "Package_Update_Type: $pkg_update_type, Package_Type: $pkg_type, "
             "Architecture: $pkg_arch, Version: $pkg_ver, Priority: $pkg_priority, "
             "Section: $pkg_section, Origin: $pkg_origin, Maintainer: $pkg_maintainer, "
             "Original_Maintainer: $pkg_ori_maintainer, Bugs: $pkg_bugs, "
             "Download_Url: $pkg_pos, Size: $pkg_size, Installed_Size: $pkg_install_size, "
             "Description: $pkg_description, Source: $pkg_source, Homepage: $pkg_homepage, "
             "Supported: $pkg_support, Multi_Arch: $pkg_multi_arch, Task: $pkg_task, "
             "Depends: $pkg_depends, Pre_Depends: $pkg_pre_depends, Recommends: $pkg_recommends, "
             "Suggests: $pkg_suggests, Enhances: $pkg_enhances, Breaks: $pkg_breaks, "
             "Conflicts: $pkg_conflicts, Replaces: $pkg_replaces, Provides: $pkg_provides})"
             "RETURN id(n)"
             )
    pkg_node_id = tx.run(query,
                         pkg_id=pkg_id, is_finish=True,
                         pkg_name=pkg_name, ubuntu_release_name=ubuntu_release_name,
                         pkg_update_type=pkg_update_type, pkg_type=pkg_type,
                         pkg_arch=pkg_arch, pkg_ver=pkg_ver, pkg_priority=pkg_priority,
                         pkg_section=pkg_section, pkg_origin=pkg_origin, pkg_maintainer=pkg_maintainer,
                         pkg_ori_maintainer=pkg_ori_maintainer, pkg_bugs=pkg_bugs,
                         pkg_pos=pkg_pos, pkg_size=pkg_size, pkg_install_size=pkg_install_size,
                         pkg_description=pkg_description, pkg_source=pkg_source, pkg_homepage=pkg_homepage,
                         pkg_support=pkg_support, pkg_multi_arch=pkg_multi_arch, pkg_task=pkg_task,
                         pkg_depends=pkg_depends, pkg_pre_depends=pkg_pre_depends, pkg_recommends=pkg_recommends,
                         pkg_suggests=pkg_suggests, pkg_enhances=pkg_enhances, pkg_breaks=pkg_breaks,
                         pkg_conflicts=pkg_conflicts, pkg_replaces=pkg_replaces, pkg_provides=pkg_provides).single()[0]

    # 创建维护者节点
    if pkg_maintainer != "":
        maintainer_name, maintainer_email = ana_maintainer(pkg_maintainer)
        # 先查询有没有这个维护者
        query = (
            "MATCH (n:Maintainer {Name: $maintainer_name, E_mail: $maintainer_email}) RETURN id(n)"
        )
        maintainer_node_id = tx.run(query, maintainer_name=maintainer_name, maintainer_email=maintainer_email).single()
        if maintainer_node_id is None:
            query = (
                "CREATE (n:Maintainer {Name: $maintainer_name, E_mail: $maintainer_email})  RETURN id(n)"
            )
            maintainer_node_id = tx.run(query, maintainer_name=maintainer_name, maintainer_email=maintainer_email).single()[0]
        else:
            maintainer_node_id = maintainer_node_id[0]
        # 构建维护者关系 (这里想使用neo4j内部id，但可能存在潜在安全问题)
        query = (
            "MATCH (m:Package) WHERE (id(m) = $pkg_node_id) "
            "MATCH (n:Maintainer) WHERE (id(n) = $maintainer_node_id)  "
            "MERGE (m)-[:Maintained_By]->(n) "
            "RETURN m,n"
        )
        asd = tx.run(query, pkg_node_id=pkg_node_id, maintainer_node_id=maintainer_node_id).single()


if __name__ == '__main__':
    # generate_query()
    parser = argparse.ArgumentParser()  # 创建一个解析对象
    parser.add_argument('--json_path', default='./xenial')
    parser.add_argument('--neo4j_uri', default=sdp_uri)
    parser.add_argument('--db_username', default=sdp_username)
    parser.add_argument('--db_password', default=sdp_password)
    json_names = []
    all_keys = {}
    args = parser.parse_args()
    for _, _, fs in os.walk(args.json_path):
        json_names = fs
    driver = GraphDatabase.driver(args.neo4j_uri, auth=(args.db_username, args.db_password),
                                  max_connection_lifetime=3600 * 24 * 30, keep_alive=True)
    with driver.session() as session:
        for json_name in json_names:
            if not json_name.__contains__(".json"):  # 排除掉中间文件和gz文件
                continue
            with open(args.json_path + "/" + json_name, 'r', encoding='utf8')as fp:
                packages_store_dict = json.load(fp)
                for key, package_dict in packages_store_dict.items():
                    session.write_transaction(analyse_package, package_dict)  # 分析单个包
                    # find_all_keys(package_dict)
            print("finished " + json_name)
    # with open("./all_keys.json", "w", encoding='utf-8') as f1:  ## 设置'utf-8'编码
        # f1.write(json.dumps(global_all_keys, ensure_ascii=False, indent=2, separators=(',', ': ')))  # (先转换成字符串再存储)
    driver.close()